home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / TEMP / GNU / bison / SemanticTo < prev    next >
Text File  |  1995-06-28  |  3KB  |  84 lines

  1. Semantic Tokens
  2. Previous: <Context Dependency=>ContextDep> * Next: <Lexical Tie-ins=>LexicalTie> * Up: <Context Dependency=>ContextDep>
  3.  
  4. #Wrap on
  5. {fH3}Semantic Info in Token Types{f}
  6.  
  7. The C language has a context dependency: the way an identifier is used
  8. depends on what its current meaning is.  For example, consider this:
  9.  
  10. #Wrap off
  11. #fCode
  12. foo (x);
  13. #f
  14. #Wrap on
  15.  
  16. This looks like a function call statement, but if {fCode}foo{f} is a typedef
  17. name, then this is actually a declaration of {fCode}x{f}.  How can a Bison
  18. parser for C decide how to parse this input?
  19.  
  20. The method used in GNU C is to have two different token types,
  21. {fCode}IDENTIFIER{f} and {fCode}TYPENAME{f}.  When {fCode}yylex{f} finds an
  22. identifier, it looks up the current declaration of the identifier in order
  23. to decide which token type to return: {fCode}TYPENAME{f} if the identifier is
  24. declared as a typedef, {fCode}IDENTIFIER{f} otherwise.
  25.  
  26. The grammar rules can then express the context dependency by the choice of
  27. token type to recognize.  {fCode}IDENTIFIER{f} is accepted as an expression,
  28. but {fCode}TYPENAME{f} is not.  {fCode}TYPENAME{f} can start a declaration, but
  29. {fCode}IDENTIFIER{f} cannot.  In contexts where the meaning of the identifier
  30. is {fEmphasis}not{f} significant, such as in declarations that can shadow a
  31. typedef name, either {fCode}TYPENAME{f} or {fCode}IDENTIFIER{f} is
  32. accepted---there is one rule for each of the two token types.
  33.  
  34. This technique is simple to use if the decision of which kinds of
  35. identifiers to allow is made at a place close to where the identifier is
  36. parsed.  But in C this is not always so: C allows a declaration to
  37. redeclare a typedef name provided an explicit type has been specified
  38. earlier:
  39.  
  40. #Wrap off
  41. #fCode
  42. typedef int foo, bar, lose;
  43. static foo (bar);        \/\* redeclare {fCode}bar{f} as static variable \*\/
  44. static int foo (lose);   \/\* redeclare {fCode}foo{f} as function \*\/
  45. #f
  46. #Wrap on
  47.  
  48. Unfortunately, the name being declared is separated from the declaration
  49. construct itself by a complicated syntactic structure---the ``declarator''.
  50.  
  51. As a result, the part of Bison parser for C needs to be duplicated, with
  52. all the nonterminal names changed: once for parsing a declaration in which
  53. a typedef name can be redefined, and once for parsing a declaration in
  54. which that can't be done.  Here is a part of the duplication, with actions
  55. omitted for brevity:
  56.  
  57. #Wrap off
  58. #fCode
  59. initdcl:
  60.           declarator maybeasm '='
  61.           init
  62.         | declarator maybeasm
  63.         ;
  64.  
  65. notype\_initdcl:
  66.           notype\_declarator maybeasm '='
  67.           init
  68.         | notype\_declarator maybeasm
  69.         ;
  70. #f
  71. #Wrap on
  72.  
  73. Here {fCode}initdcl{f} can redeclare a typedef name, but {fCode}notype\_initdcl{f}
  74. cannot.  The distinction between {fCode}declarator{f} and
  75. {fCode}notype\_declarator{f} is the same sort of thing.
  76.  
  77. There is some similarity between this technique and a lexical tie-in
  78. (described next), in that information which alters the lexical analysis is
  79. changed during parsing by other parts of the program.  The difference is
  80. here the information is global, and is used for other purposes in the
  81. program.  A true lexical tie-in has a special-purpose flag controlled by
  82. the syntactic context.
  83.  
  84.